"""
任务1：PCA和LDA降维 - Wine数据集
从UCI下载Wine数据，只保留类别1和2，进行PCA和LDA降维
"""

import numpy as np
from sklearn.datasets import load_wine


def pca(X, k=2):
    """PCA主成分分析"""
    X_centered = X - np.mean(X, axis=0)
    cov_matrix = np.cov(X_centered.T)
    eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
    idx = np.argsort(eigenvalues)[::-1]
    eigenvectors = eigenvectors[:, idx[:k]]
    X_pca = X_centered @ eigenvectors
    return X_pca


def lda(X, y, k=2):
    """LDA线性判别分析"""
    n_features = X.shape[1]
    class_labels = np.unique(y)
    mean_total = np.mean(X, axis=0)

    SW = np.zeros((n_features, n_features))
    SB = np.zeros((n_features, n_features))

    for c in class_labels:
        X_c = X[y == c]
        mean_c = np.mean(X_c, axis=0)
        SW += (X_c - mean_c).T @ (X_c - mean_c)
        n_c = X_c.shape[0]
        mean_diff = (mean_c - mean_total).reshape(n_features, 1)
        SB += n_c * (mean_diff @ mean_diff.T)

    eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(SW) @ SB)
    idx = np.argsort(eig_vals.real)[::-1]
    W = eig_vecs.real[:, idx[:k]]

    return X @ W


def main():
    print("=== 任务1：Wine数据PCA和LDA降维 ===\n")

    # 加载数据
    wine = load_wine()
    X, y = wine.data, wine.target

    print(f"原始数据: {X.shape}")
    print(f"类别分布: {np.bincount(y)}")

    # 筛选类别1和2（对应原始标签0和1）
    mask = (y == 0) | (y == 1)
    X_filtered, y_filtered = X[mask], y[mask]

    print(f"筛选后数据: {X_filtered.shape}")

    # PCA降维
    X_pca = pca(X_filtered, k=2)
    print("\nPCA降维结果（前5个样本）:")
    for i in range(5):
        print(f"样本{i + 1}: [{X_pca[i, 0]:.6f}, {X_pca[i, 1]:.6f}]")

    # LDA降维
    X_lda = lda(X_filtered, y_filtered, k=2)
    print(f"\nLDA降维结果（前5个样本）:")
    for i in range(5):
        print(f"样本{i + 1}: [{X_lda[i, 0]:.6f}, {X_lda[i, 1]:.6f}]")


if __name__ == "__main__":
    main()